package com.nightsoul.servlet3.test.chapter4.web;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.Executors;

import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletException;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet如果要支持异步，那么拦截此Servlet的Filter也要支持异步
 * 异步Servlet并不能缩短响应时间，只能提高吞吐量
 * @author zj
 *
 */
@WebServlet(name="myAsyncServlet", urlPatterns="/myasync", asyncSupported=true)
public class MyAsyncServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)	throws ServletException, IOException {
		System.out.println(request.isAsyncSupported());
		final AsyncContext asyncContext = request.startAsync();
		asyncContext.setTimeout(5000);

		long startTime = System.currentTimeMillis();
        System.out.println("LongRunningServlet Start::Name="
                + Thread.currentThread().getName() + "::ID="
                + Thread.currentThread().getId());

        String time = request.getParameter("time");
        if(time==null) {
        	time = "10000";
        }
        int secs = Integer.valueOf(time);
        // max 10 seconds
        if (secs > 10000)
            secs = 10000;


        asyncContext.addListener(new AsyncListener() {

			@Override
			public void onTimeout(AsyncEvent event) throws IOException {
				System.out.println("AsyncListener onTimeout");
		        //we can send appropriate response to client
		        ServletResponse response = event.getAsyncContext().getResponse();
		        PrintWriter out = response.getWriter();
		        out.write("TimeOut Error in Processing");
			}

			@Override
			public void onStartAsync(AsyncEvent event) throws IOException {
				System.out.println("AsyncListener onStartAsync");
			}

			@Override
			public void onError(AsyncEvent event) throws IOException {
				System.out.println("AsyncListener onError");
			}

			@Override
			public void onComplete(AsyncEvent event) throws IOException {
				System.out.println("AsyncListener onComplete");
			}
		});

        final int processTime = secs;
        Executors.newCachedThreadPool().execute(new Runnable() {

			@Override
			public void run() {
				longProcessing(processTime);
				asyncContext.complete();
			}
		});



        PrintWriter out = response.getWriter();
        long endTime = System.currentTimeMillis();
        // write不会阻塞，会在异步请求完成之前再输出至客户端
        out.write("Processing done for " + secs + " milliseconds!!");
        System.out.println("LongRunningServlet Start::Name="
                + Thread.currentThread().getName() + "::ID="
                + Thread.currentThread().getId() + "::Time Taken="
                + (endTime - startTime) + " ms.");
	}

	 private void longProcessing(int secs) {
        // wait for given time before finishing
        try {
            Thread.sleep(secs);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
